//Gloabal Variables - Passed in from the Application
float4x4 worldViewProjMat;				 //Transform vertex pos to view space
float4x4 worldInverseTransposeMat;		 //Transforms vertex normals to world space
float4x4 worldMat;						 //World Matrix

float3 eyePos;							 //Camera or Eye Position

//Light Parameters
float3 lightPos;						 //Assuming we have a point light
float3 ambientLight;					 //Light Ambient Color
float3 diffuseLight;					 //Light diffuse Color
float3 specularLight;					 //Light specular Color
float3 lightAttenuation;				 //Light attenuation (atten0, atten1, atten2)

//Material Parameters
float4 ambientMaterial;					 //Material Ambient Color
float4 diffuseMaterial;					 //Material diffuse Color
float4 specularMaterial;				 //Material specular Color
float specularPower;					 //Material specular highlight power

//Texture
texture tex;							 //Diffuse image texture to apply to object
bool hasTexture = true;					 //Boolean to check to see if the specific mesh has a texture

sampler texSamp = sampler_state
{
	Texture = <tex>;
	
	//Trilinear Filter
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	
	//specifying address mode, Address filter = wrap
};

//Vertex output structure
struct VS_OUT
{
	float4 posH : POSITION0;			 //Vertex position in homogenous clip space
	float3 normW : TEXCOORD0;			 //Vertex normal in world space
	float3 posW : TEXCOORD1;			 //Vertex pos in world space
	float2 tex0 : TEXCOORD2;			 //Vertex uv coordinates
};

//Vertex Shader
VS_OUT VS(float3 pos : POSITION0, float3 norm : NORMAL0, float2 tex0 : TEXCOORD0)
{
	VS_OUT vsOut = (VS_OUT)0;
	
	//Transform vertex pos to homogenous clip space (pos * World View Projection)
	vsOut.posH = mul(float4(pos, 1.0f), worldViewProjMat);
	
	//Transform vertex pos to world space (pos * worldMat)
	vsOut.posW = mul(float4(pos, 1.0f), worldMat).xyz;
	
	//Transform vertex normal to world space
	vsOut.normW = mul(float4(norm,1.0f), worldInverseTransposeMat).xyz;
	
	//Normalize the normals
	vsOut.normW = normalize(vsOut.normW);
	
	//Pass on the texture coordinates to the pixel shader
	vsOut.tex0 = tex0;
	
	return vsOut;
}

//Pixel Shader
float4 PS(VS_OUT vsOut) : COLOR
{
	//Get the texel from the texture map and map to pixel
	float3 texColor;
	if(hasTexture)
	{
		 texColor = tex2D(texSamp, vsOut.tex0).rgb;
	}
	
	//Interpolated normals in VS, can "unnormalize", so normalize again
	vsOut.normW = normalize(vsOut.normW);
	
	//Compute the vector from the vertex to the eye pos (V)
	float3 toEye = normalize(eyePos - vsOut.posW);
	
	//Light Direction Vector (L)
	float3 lightDir = normalize(lightPos - vsOut.posW);
	
	//Determine how much specular (if any), makes it to the eye
	
	//Phong Specular calculation (for future reference)
	//Calculate the reflection vector (R)
	//float3 R = reflect(-lightDir, vsOut.normW);
	//float T = pow(max(dot(R, toEye), 0.0f), specularPower);
	
	//Blinn-Phong Specular calculation
	//Half Vector is used in Blinn-Phong shading(rather than calculating Reflection)(R)
	float3 H = normalize(lightDir + normalize(toEye));
	float T = pow(max(dot(H, vsOut.normW), 0.0f), specularPower);
	
	//Determine the diffuse light intensity
	float S = max(dot(lightDir, vsOut.normW), 0.0f);
	
	//Compute Ambient, Diffuse, and Specular terms seperately
	float3 spec;
	float3 diffuse;
	float3 ambient;
	
	if(hasTexture)
	{
		spec = T * (specularMaterial * specularLight).rgb;
		diffuse = S * (diffuseMaterial * texColor * diffuseLight).rgb;
		ambient = (ambientMaterial * ambientLight * texColor);
	}
	else
	{
		spec = T * (specularMaterial * specularLight).rgb;
		diffuse = S * (diffuseMaterial * diffuseLight).rgb;
		ambient = (ambientMaterial * ambientLight);
	}
	
	//Attenuation
	float d = distance(lightPos, vsOut.posW);
	float A = lightAttenuation.x + lightAttenuation.y * d + lightAttenuation.z * d * d;
	
	//Sum all of the terms together and just copy the diffuse's alpha
	return float4(ambient + (diffuse + spec) / A, diffuseMaterial.a);
}

//Techniques and Passes
technique tech0
{
	pass p0
	{
		//Specify vertex and pixel shader associated with this pass
		//need to use 2.0 mainly because this netbook doesn't support 3.0
		vertexShader = compile vs_3_0 VS();		//VS 2.0
		pixelShader = compile ps_3_0 PS();		//PS 2.0
		
		//Set any needed render states for this pass
		
		//Alpha components
		//AlphaBlendEnable = true;
		//SrcBlend = SrcAlpha;
		//DestBlend = InvSrcAlpha;
		//BlendOp = Add;
		//CullMode = None;
	}
}